from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QWidget, QLabel, QLineEdit, QBoxLayout, QVBoxLayout, QHBoxLayout, QTextEdit, QDialog, \
    QGridLayout, QDialogButtonBox, QApplication

LEFT = 0
ABOVE = 1


class LabelledLineEdit(QWidget):
    def __init__(self, labelText="", position=LEFT, parent=None):
        super(LabelledLineEdit, self).__init__(parent)

        self.label = QLabel(labelText)
        self.lineEdit = QLineEdit()
        self.label.setBuddy(self.lineEdit)
        layout = QHBoxLayout() if position == LEFT else QVBoxLayout()
        layout.addWidget(self.label)
        layout.addWidget(self.lineEdit)
        self.setLayout(layout)


class LabelledTextEdit(QWidget):
    def __init__(self, labelText="", position=LEFT, parent=None):
        super(LabelledTextEdit, self, ).__init__(parent)
        self.label = QLabel(labelText)
        self.textEdit = QTextEdit()
        layout = QHBoxLayout() if position == LEFT else QVBoxLayout()
        layout.addWidget(self.label)
        layout.addWidget(self.textEdit)
        self.setLayout(layout)


class Form(QDialog):
    def __init__(self, parent=None):
        super(Form, self).__init__(parent)
        self.setWindowTitle("Complex Widget")

        w1 = LabelledLineEdit(labelText="Street")
        w2 = LabelledLineEdit(labelText="City")
        w3 = LabelledLineEdit(labelText="Status")
        w4 = LabelledLineEdit(labelText="zipCode")

        w5 = LabelledTextEdit(labelText="Notes", position=ABOVE)

        btnBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)

        gridLayout = QGridLayout()
        gridLayout.addWidget(w1, 0, 0)
        gridLayout.addWidget(w2, 0, 1)
        gridLayout.addWidget(w3, 1, 0)
        gridLayout.addWidget(w4, 1, 1)

        vlayout = QVBoxLayout()
        vlayout.addLayout(gridLayout)
        vlayout.addWidget(w5)
        vlayout.addWidget(btnBox, alignment=Qt.AlignRight)

        self.setLayout(vlayout)


if __name__ == '__main__':
    import sys

    app = QApplication(sys.argv)
    form = Form()
    form.show()
    sys.exit(app.exec())
